﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using AliyunOSServiceLib.Services;
using Ceremony.API.Application.Queries;
using Ceremony.API.Model;
using Ceremony.API.ParameterModel;
using Ceremony.API.ViewModel;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;

namespace Ceremony.API.Controllers
{
    [Route("api/v1/ceremony")]
    [ApiController]
    public class YaoyiyaoController : ControllerBase
    {
        private readonly ILogger<YaoyiyaoController> _logger;
        private readonly CeremonyContext _context;
        private readonly ICeremonyQueries _queries;
        private readonly CeremonySettings _settings;
        private readonly IAliyunOSService _aliyunOSService;
        public YaoyiyaoController(ILogger<YaoyiyaoController> logger, 
            CeremonyContext context, 
            ICeremonyQueries queries,
            IOptionsSnapshot<CeremonySettings> settings,
            IAliyunOSService aliyunOSService)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _queries = queries ?? throw new ArgumentNullException(nameof(queries));
            _settings = settings.Value ?? throw new ArgumentNullException(nameof(settings));
            _aliyunOSService = aliyunOSService ?? throw new ArgumentNullException(nameof(aliyunOSService));


        }
        /// <summary>
        /// 开始抽奖
        /// </summary>
        /// <returns></returns>
        [Route("yaoyiyao/start")]
        [HttpPost]
        [ProducesResponseType((int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public async Task<IActionResult> StartPrize([FromBody]StartPrizeParmeter startPrize)
        {
            var prizeSettings = _context.PrizeSettings.Where(t => t.Scene == startPrize.Scene);
            if(!prizeSettings.Any())
            {
                return Ok(new PrizeStartModel { Scene = startPrize.Scene, ResponseCode = 0 });
            }
            var prizes = _context.Prizes.Where(t => t.Scene == startPrize.Scene);
            if(prizes.Count() > 0)
            {
                //删除所有key
                var keys = RedisHelper.Keys("*");
                await RedisHelper.DelAsync(keys);
                foreach (var item in prizes)
                {
                    var prizeModel = new PrizeStarttingModel
                    {
                        PrizeId = item.Id,
                        PrizeName = item.PrizeName,
                        Level = item.Level,
                        Tag = item.Tag,
                        ImageName = item.ImageName,
                        StartTime = DateTime.Now
                    };
                    if (!string.IsNullOrEmpty(item.PrizeName))
                    {
                        var picUrls = GetPicUrl(_settings.WechatMomentImagePath, item.ImageName,_settings.ProcessSmall);
                        if (picUrls.Count() > 0)
                        {
                            prizeModel.ImageUrl = picUrls.FirstOrDefault().Url;
                        }
                    }
                    var json = JsonConvert.SerializeObject(prizeModel);
                    await RedisHelper.SAddAsync("prizes",json);
                    await RedisHelper.SetAsync(item.Id.ToString(), item.Num);
                }
                //1：开始 2：当场已结束
                PrizeStateModel prizeStateModel = new PrizeStateModel
                {
                    Scene = startPrize.Scene,
                    State = 1
                };
                await RedisHelper.SetAsync("currentstate", prizeStateModel);
            }
            else
            {
                return Ok(new PrizeStartModel { Scene = startPrize.Scene, ResponseCode = 1 });
            }
            return Ok(new PrizeStartModel { Scene = startPrize.Scene, ResponseCode = 2 });
        }
        /// <summary>
        /// 摇一摇
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [Route("yaoyiyao")]
        [HttpPost]
        [ProducesResponseType(typeof(PrizeViewModel),(int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public async Task<ActionResult<PrizeViewModel>> PostYaoyiyao([FromBody]YaoyiyapUser user)
        {
            var findUser = await _context.Users.FindAsync(user.UserId);
            if(findUser == null || string.IsNullOrEmpty(findUser.AuthorizeCode) || findUser.OpenId != user.OpenId)
            {
                return Ok(new PrizeViewModel { ResponseCode = 3 });
            }
            var keys = await RedisHelper.KeysAsync("*");
            if(keys.Contains("currentstate"))
            {
                var currentState = await RedisHelper.GetAsync<PrizeStateModel>("currentstate");
                if (currentState.State == 1)
                {
                    //奖项总数量
                    int total = 0;
                    //奖项ID和数量的字典
                    Dictionary<int, int> myPrizeDic = new Dictionary<int, int>();
                    for (int i = 0; i < keys.Length; i++)
                    {
                        if (keys[i].Equals("currentstate") 
                            || keys[i].Equals("prizes") 
                            || keys[i].Equals(_settings.ChannelTaskName)
                            || keys[i].Equals(_settings.ChannelQuartzTaskName))
                        {
                            continue;
                        }
                        try
                        {
                            int num = await RedisHelper.GetAsync<int>(keys[i]);
                            myPrizeDic.Add(int.Parse(keys[i]), num);
                            total += num;
                        }
                        catch { }
                    }
                    Random random = new Random();
                    int randonNum = random.Next(1, total + 1);
                    int sum = 0;
                    foreach (var item in myPrizeDic)
                    {
                        sum += item.Value;
                        if (randonNum <= sum)
                        {
                            int currentNum = item.Value - 1;
                            if (currentNum == 0)
                            {
                                await RedisHelper.DelAsync(item.Key.ToString());
                            }
                            else
                            {
                                RedisHelper.Set(item.Key.ToString(), currentNum);
                            }
                            var prizes = RedisHelper.SMembers("prizes");
                            for (var i = 0; i < prizes.Length; i++)
                            {
                                var prize = JsonConvert.DeserializeObject<PrizeStarttingModel>(prizes[i]);
                                if (item.Key == prize.PrizeId)
                                {
                                    PrizeViewModel pm = new PrizeViewModel();
                                    pm.ResponseCode = 1;
                                    pm.Level = prize.Level;
                                    if (pm.Level == 0)
                                    {
                                        Random rd = new Random();
                                        var prizeTitles = GetPrizeTitle();
                                        int selectTitle = rd.Next(0, prizeTitles.Count());
                                        pm.PrizeTitle = prizeTitles[selectTitle];
                                    }
                                    else
                                    {
                                        pm.PrizeTitle = "恭喜你，中奖啦！";
                                    }
                                    pm.UserId = user.UserId;
                                    pm.PrizeId = prize.PrizeId;
                                    pm.PrizeName = prize.PrizeName;
                                    //6分钟以内用原来生成的图片链接
                                    TimeSpan ts = DateTime.Now - prize.StartTime;
                                    if(ts.TotalSeconds < 360)
                                    {
                                        pm.ImageUrl = prize.ImageUrl;
                                    }
                                    else
                                    {
                                        //获取图片url
                                        if (!string.IsNullOrEmpty(prize.PrizeName))
                                        {
                                            var picUrls = GetPicUrl(_settings.WechatMomentImagePath, prize.ImageName, _settings.ProcessSmall);
                                            if (picUrls.Any())
                                            {
                                                pm.ImageUrl = picUrls.FirstOrDefault().Url;
                                            }
                                        }
                                    }
                                    pm.Tag = prize.Tag;
                                    //发布中将记录信息
                                    RedisHelper.LPush(_settings.ChannelTaskName, new PublishUserPrizeRecord
                                    {
                                        PrizeId = prize.PrizeId,
                                        UserId = user.UserId,
                                        PrizeName = prize.PrizeName,
                                        Level = prize.Level,
                                        Tag = prize.Tag,
                                        ImageName = prize.ImageName,
                                        ImageUrl = prize.ImageUrl
                                    });
                                    return Ok(pm);
                                }
                            }
                            break;
                        }
                    }
                    if (total == 0)
                    {
                        currentState.State = 2;
                        await RedisHelper.SetAsync("currentstate", currentState);
                    }
                }
                return Ok(new PrizeViewModel { ResponseCode = currentState.State,Scene= currentState.Scene });
            }
            else
            {
                return Ok(new PrizeViewModel { ResponseCode = 0 });
            }

        }
        /// <summary>
        /// 设置摇一摇时间
        /// </summary>
        /// <param name="prizeSetting"></param>
        /// <returns></returns>
        [Route("yaoyiyao/setting")]
        [HttpPost]
        [ProducesResponseType((int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public async Task<IActionResult> SetYaoyiyaoTime([FromBody]List<SetPrizeParmeter> prizeSetting)
        {
            var prizesettings = _context.PrizeSettings;
            DateTime dt = DateTime.Now;
            PrizeSetting setting = null;
            foreach(var item in prizeSetting)
            {
                try
                {
                    dt = Convert.ToDateTime(item.StartTime);
                }
                catch (Exception ex)
                {
                    _logger.LogError("时间格式错误(" + item.StartTime + "):" + ex.Message);
                    return BadRequest();
                }
                if (prizesettings.Where(t => t.Scene == item.Scene).Any())
                {
                    setting = prizesettings.Where(t => t.Scene == item.Scene).FirstOrDefault();
                    if(setting != null)
                    {
                        setting.StartTime = dt;
                        _context.PrizeSettings.Update(setting);
                    }
                }
                else
                {
                    setting = new PrizeSetting(item.Scene, dt);
                    await _context.PrizeSettings.AddAsync(setting);
                }
            }
            
            int result = await _context.SaveChangesAsync();
            string resultStr = result > 0 ? "succeed" : "failed";
            _logger.LogInformation("----- operate PrizeSetting {Result}: - ({@PrizeSetting})",
                resultStr, 
                prizeSetting);
            if (result > 0)
            {
                var prizeSettings = _context.PrizeSettings;
                //发布更新时间消息
                RedisHelper.LPush(_settings.ChannelQuartzTaskName, prizeSettings);
                return Ok();
            }
            else
            {
                return BadRequest();
            }
        }

        /// <summary>
        /// 重置摇一摇
        /// </summary>
        /// <returns></returns>
        [Route("yaoyiyao/reset")]
        [HttpPost]
        [ProducesResponseType((int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public async Task<IActionResult> ResetYaoyiyao([FromBody]ResetPrizeParmeter parameter)
        {
            if (!parameter.Password.Equals("lsh0599024"))
                return BadRequest();
            //删除所有key
            var keys = RedisHelper.Keys("*");
            await RedisHelper.DelAsync(keys);
            return Ok();
        }
        /// <summary>
        /// 获取摇一摇时间
        /// </summary>
        /// <param name="prizeSetting"></param>
        /// <returns></returns>
        [Route("yaoyiyao/settings")]
        [HttpGet]
        [ProducesResponseType((int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public IActionResult GetYaoyiyaoTimes()
        {
            var prizesettings = _context.PrizeSettings.OrderBy(t => t.StartTime);
            List<ReturnPrizeSetting> prizeSettings = new List<ReturnPrizeSetting>();
            foreach(var item in prizesettings)
            {
                prizeSettings.Add(new ReturnPrizeSetting
                {
                    Id = item.Id,
                    Scene = item.Scene,
                    StartTime = item.StartTime,
                    StartTimeFormat = item.StartTime.ToString("yyyy/MM/dd HH:mm")
                });
            }
            return Ok(prizeSettings);
        }
        /// <summary>
        /// 获取倒计时和滚动通知
        /// </summary>
        /// <returns></returns>
        [Route("yaoyiyao/cutdown")]
        [HttpGet]
        [ProducesResponseType((int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public async Task<IActionResult> GetYaoyiyaoTime()
        {
            DateTime dt = DateTime.Now;
            var prizeSettings = _context.PrizeSettings.OrderBy(t => t.Scene);
            string noticeMessage = "";
            var notice = _context.Notices.FirstOrDefault();
            if (notice != null)
            {
                noticeMessage = notice.Message;
            }
            if (!prizeSettings.Any())
            {
                return Ok(new CutDownModel
                {
                    CutDown = 0,
                    NoticeMessage = noticeMessage
                });
            }
            else
            {
                string[] keys = await RedisHelper.KeysAsync("*");
                CutDownModel cutDownModel = new CutDownModel();
                //还未开始
                if (keys.Length == 0 || !keys.Contains("currentstate"))
                {
                    var set = prizeSettings.FirstOrDefault();
                    double totalSceonds = (set.StartTime - dt).TotalSeconds;
                    if (totalSceonds > 0)
                    {
                        cutDownModel.CutDown = Convert.ToInt32(totalSceonds);
                    }
                }
                else
                {
                    var currentState = await RedisHelper.GetAsync<PrizeStateModel>("currentstate");
                    if(currentState.State == 1)
                    {
                        cutDownModel.CutDown = 0;
                    }
                    //当场结束
                    else if(currentState.State == 2)
                    {
                        int scene = currentState.Scene;
                        if(scene < prizeSettings.Count())
                        {
                            //下一场时间
                           var set = prizeSettings.Where(t => t.Scene == scene + 1).FirstOrDefault();
                           if(set != null)
                            {
                                double totalSceonds = (set.StartTime - dt).TotalSeconds;
                                if (totalSceonds > 0)
                                {
                                    cutDownModel.CutDown = Convert.ToInt32(totalSceonds);
                                }
                            }
                        }
                    }
                }
                cutDownModel.NoticeMessage = noticeMessage;
                return Ok(cutDownModel);
            }
        }

        /// <summary>
        /// 设置摇一摇通知信息
        /// </summary>
        /// <returns></returns>
        [Route("yaoyiyao/notice")]
        [HttpPost]
        [ProducesResponseType((int)HttpStatusCode.OK)]
        [ProducesResponseType((int)HttpStatusCode.BadRequest)]
        public async Task<IActionResult> SetYaoyiyaoNotice([FromBody]YaoyiyaoNoticeParameter parameter)
        {
            if(parameter.Password != "lsh0599024")
            {
                return BadRequest();
            }
            else
            {
                var notice = _context.Notices.FirstOrDefault();
                if(notice == null)
                {
                    notice = new Notice(parameter.Message);
                    await _context.Notices.AddAsync(notice);
                }
                else
                {
                    notice.Message = parameter.Message;
                    _context.Notices.Update(notice);
                }
                var result = await _context.SaveChangesAsync();
                string resultStr = result > 0 ? "succeed" : "failed";
                _logger.LogInformation("----- Operate Notice {Result}: - {IdProperty}: {NoticeId} ({@Notice})",
                    resultStr,
                    nameof(notice.Id),
                    notice.Id,
                    notice);
                if (result > 0)
                {
                    return Ok();
                }
                else
                {
                    return BadRequest();
                }
            }
        }
        private List<FileUrl> GetPicUrl(string objectName, string picNames,string process="")
        {
            try
            {
                if (string.IsNullOrEmpty(picNames) || string.IsNullOrEmpty(objectName))
                    return null;
                List<FileUrl> files = new List<FileUrl>();
                string[] picArray = picNames.Trim(';').Split(';');
                for (int i = 0; i < picArray.Length; i++)
                {
                    string key = objectName + "/" + picArray[i];
                    string url = _aliyunOSService.GetGeneratePresignedUri(key, process);
                    files.Add(new FileUrl { Name = picArray[i], Url = url });
                }
                return files;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
            }
            return null;
        }

        private List<string> GetPrizeTitle()
        {
            List<string> prizeTitles = new List<string>();
            prizeTitles.Add("摇不中啊换个姿势吧!");
            prizeTitles.Add("当心手机别摇地上去了!");
            prizeTitles.Add("你长得太帅，红包被你亮瞎眼了!");
            prizeTitles.Add("悄悄问新郎新娘怎么会中奖!");
            prizeTitles.Add("天上掉下一个林妹妹，溜了!");
            prizeTitles.Add("没中？酒喝少了!");
            prizeTitles.Add("一大波奖品正在路上!");
            prizeTitles.Add("新年好，给你拜个年!");
            prizeTitles.Add("手机不行，换个试试？");
            prizeTitles.Add("吃的饱饱的，才有力气摇!");
            prizeTitles.Add("喝酒，喝酒，干了!");
            return prizeTitles;
        }
    }
}